(function(window) {
	
	/* **************************************** */
	/* Helpers */
	
	var ItemWrapper = function(el) {
		this.el = el;
		this.html = function(html) {
			return html === undefined ?
				el.innerHTML:
				el.innerHTML = html;
		};
		this.css = function(k,v) {
			if(typeof(k) == 'string') {
				el.style[k] = v;
			} else if(typeof(k) == 'object') {
				for(var kk in k) {
					el.style[kk] = k[kk];
				}
			}
		};
		this.value = function(v) {
			if(v === undefined) {
				v = (!(el instanceof HTMLInputElement) ?
					(el instanceof HTMLTextAreaElement ? el['value']: ''):
					(el.type == 'checkbox' || el.type == 'radio' ?
						el['checked']: el['value']));
			} else {
				if(!(el instanceof HTMLInputElement)) {
					if(el instanceof HTMLTextAreaElement) {
						el['value'] = v;
					}
				} else if(el.type == 'checkbox' || el.type == 'radio') {
					el['checked'] = (v ? true: false);
				} else {
					el['value'] = v;
				}
			}
			return v;
		};
		this.width = function() {
			return 'clientWidth' in el ? el['clientWidth']: 0;
		};
		this.height = function() {
			return 'clientHeight' in el ? el['clientHeight']: 0;
		};
		this.offset = function() {
			var x = 0;
			var y = 0;
			var elz = el;
			var i = 0;
			while(elz && !isNaN(elz.offsetLeft) && !isNaN(elz.offsetTop)) {
				x += elz.offsetLeft - elz.scrollLeft;
				y += elz.offsetTop - elz.scrollTop;
				elz = elz.parentNode;
			}
			return { top: y, left: x };
		}
		this.hasClass = function(cname) {
			return (!el ? false: el.className.split(' ').indexOf(cname) >= 0);
		};
		this.addClass = function(cname) {
			if(!el) return;
			var arr = el.className.split(' ');
			if(arr.indexOf(cname) >= 0) return;
			arr.push(cname);
			el.className = arr.join(' ');
		};
		this.removeClass = function(cname) {
			if(!el) return;
			var arr = el.className.split(' ');
			var idx = arr.indexOf(cname);
			if(idx < 0) return;
			arr.splice(idx, 1);
			el.className = arr.join(' ');
		};
		this.toggleClass = function(cname) {
			if(this.hasClass(cname)) {
				this.removeClass(cname);
			} else {
				this.addClass(cname);
			}
		};
		this.attr = function(key, val) {
			if(!el) return;
			if(val === undefined)
				return el.getAttribute(key);
			el.setAttribute(key, val);
			return val;
		};
		this.append = function(el2) {
			el.appendChild(el2);
		};
		this.remove = function() {
			el.parentNode ? el.parentNode.removeChild(el): 1;
		};
		this.tween = function(transition) {
			el.style.WebkitTransition = transition;
			el.style.MozTransition = transition;
			el.style.OTransition = transition;
			el.style.MSTransition = transition;
		};
	};
	
	var wrapArray = function(arr) {
		var r = [];
		for(var i = 0; i < arr.length; ++i)
			r.push(new ItemWrapper(arr[i]));
		
		/* -------------------------------- */
		/* --- OVERRIDE ------------------- */
		
		r.indexOf = function(element) {
			for(var j = 0; j < r.length; ++j)
				if(r[j].el == element) return j;
			return -1;
		};
		
		/* -------------------------------- */
		
		r.html = function(html) {
			for(var j = 0; j < r.length; ++j) r[j].html(html);
		};
		r.css = function(css) {
			for(var j = 0; j < r.length; ++j) r[j].css(css);
		};
		r.attr = function(key, val) {
			if(val === undefined)
				return r.length > 0 ? r[0].attr(key): undefined;
			for(var j = 0; j < r.length; ++j)
				r[j].attr(key, val);
			return val;
		};
		r.tween = function(transition) {
			for(var j = 0; j < r.length; ++j) r[j].tween(transition);
		};
		r.hasClass = function(cname) {
			for(var j = 0; j < r.length; ++j)
				if(r[j].hasClass(cname)) return true;
			return false;
		};
		r.addClass = function(cname) {
			for(var j = 0; j < r.length; ++j) r[j].addClass(cname);
		};
		r.removeClass = function(cname) {
			for(var j = 0; j < r.length; ++j) r[j].removeClass(cname);
		};
		r.toggleClass = function(cname) {
			for(var j = 0; j < r.length; ++j) r[j].toggleClass(cname);
		};
		r.append = function(el2) {
			r.length < 1 ? 1: r[0].append(el2);
		};
		r.remove = function() {
			for(var j = 0; j < r.length; ++j) r[j].remove();
		};
		r.value = function(v) {
			if(v === undefined)
				return r.length < 1 ? '': r[0].value();
			for(var j = 0; j < r.length; ++j) r[j].value(v);
			return v;
		};
		r.width = function() {
			return r.length < 1 ? 0: r[0].width();
		};
		r.height = function() {
			return r.length < 1 ? 0: r[0].height();
		};
		r.offset = function() {
			return r.length < 1 ? null: r[0].offset();
		};
		return r;
	};
	
	/* **************************************** */
	/* Functions */
	
	var f_require = function(src) {
		var h = document.getElementsByTagName('head')[0];
		var script = document.createElement('script');
		script.setAttribute('type', 'text/javascript');
		script.setAttribute('src', src);
		h.appendChild(script);
	};
	
	var f_log = function() {
		for(var i = 0; i < arguments.length; ++i) {
			console.log(arguments[i]);
			// document.body.innerHTML += arguments[i] + '<br/>';
		}
	};
	
	var f_trim = function trim(s, chars) {
		if(s == null)
			return null;
		
		if(chars) {
			chars = chars.replace('-', '\\-');
			var rxLeft = new RegExp('^[\\s' + chars + ']+', 'g');
			var rxRight = new RegExp('[\\s' + chars + ']+$', 'g');
			return s.replace(rxLeft, '').replace(rxRight, '');
		}
		return s.replace(/^\s+/, '').replace(/\s+$/, '');
	};
	
	var f_make = function(tag, id, className, style) {
		var el = document.createElement(tag);
		if(id) el.setAttribute('id', id);
		if(className) el.setAttribute('class', className);
		if(style) el.setAttribute('style', style);
		return el;
	};
	
	var f_load = function(url, method, data, headers) {
		var req = new XMLHttpRequest();
		req.open(method ? method: 'get', url, true);
		if(headers !== undefined)
			for(var hname in headers)
				req.setRequestHeader(hname, headers[hname]);
		req.send(data);
		return req;
	};
	
	var f_parseVars = function(str) {
		var params = str.split('&');
		var out = {};
		for(var i = 0, arr, k, v; i < params.length; ++i) {
			arr = params[i].split('=', 2);
			if(arr.length != 2) continue;
			k = arr[0];
			v = arr[1];
			try {
				out[k] = v;
			} catch(err) { }
		}
		return out;
	};
	
	var f_parseView = function(parent, view) {
		var el = ix.make(view.tag || 'div', view.id, view.cls);
		fillElement(el, view);
		parent.appendChild(el);
		
		if(view.children)
			for(var i = 0, child; i < view.children.length; ++i)
				child = f_parseView(el, view.children[i]);
		return el;
	};
	
	var f_isArray = function(o) {
		return Object.prototype.toString.call(o) === '[object Array]';
	};
	
	/* **************************************** */
	/* Private(s) */
	
	var fillElement = function(el, v) {
		if(!isNaN(v.left) || !isNaN(v.top) || !isNaN(v.right) || !isNaN(v.bottom)) {
			el.style.position = 'absolute';
			if(!isNaN(v.left)) el.style.left = v.left + 'px';
			if(!isNaN(v.top)) el.style.top = v.top + 'px';
			if(!isNaN(v.right)) el.style.right = v.right + 'px';
			if(!isNaN(v.bottom)) el.style.bottom = v.bottom + 'px';
		}
		if(!isNaN(v.width)) el.style.width = v.width + 'px';
		if(!isNaN(v.height)) el.style.height = v.height + 'px';
		if(!isNaN(v.z)) el.style.zIndex = v.z;
		
		if(v.id) el.id = v.id;
		if(v.src) el.src = v.src;
		if(v.html) el.innerHTML = v.html;
		if(v.attr) for(var k in v.attr) el.setAttribute(k, v.attr[k]);
	};
	
	/* **************************************** */
	/* Aliases */
	
	var log = f_log;
	
	/* **************************************** */
	/* Class */
	
	window.ix = function() {
		var argc = arguments.length;
		if(argc == 1) {
			var arg = arguments[0];
			if(typeof(arg) == 'string') {
				var r = document.querySelectorAll(arguments[0]);
				return wrapArray(r);
			} else {
				return new ItemWrapper(arg);
			}
		} else {
			log('unknown arguments (' + argc + ' args here)');
			return null;
		}
		return this;
	};
	
	window.ix.log = f_log;
	window.ix.trim = f_trim;
	window.ix.make = f_make;
	window.ix.load = f_load;
	window.ix.isArray = f_isArray;
	window.ix.require = f_require;
	window.ix.parseVars = f_parseVars;
	window.ix.parseView = f_parseView;
	window.ix.dropEvent = function(event) { event.preventDefault(); };
	
}(window))
